home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / fortran / toolpack.000 / toolpack / toolpack1.2 / C / allio.c next >
Encoding:
C/C++ Source or Header  |  1993-10-16  |  37.5 KB  |  1,656 lines

  1. /*-------------------------------*/
  2. /*   TOOLPACK/1   Release: 1.1   */
  3. /*-------------------------------*/
  4. #include <ctype.h>
  5. #include "define.h"
  6.  
  7. #include <sys/types.h>
  8. #include <sys/time.h>
  9. #ifdef sgi
  10. #include <time.h>
  11. #endif
  12.  
  13. #include <sys/stat.h>
  14.  
  15. #include <sys/dir.h>
  16.  
  17. #include "globals1.h"
  18. #include "globals2.h"
  19. #include "globals.h"
  20.  
  21. acopy_(fdi, fdo, size)
  22. int *fdi, *fdo, *size;
  23.  
  24. {
  25.     /* copy size characters from the input file fdi to the output
  26.        file fdo. If eof encountered on fdi before the transfer is
  27.        complete the transfer is immediately terminated. Both files
  28.        are assumed sequential */
  29.  
  30.     int c, i;
  31.  
  32.     /* ensure input file open for read and output file for write */
  33.     if (opnread(*fdi) == ERR || opnwrit(*fdo) == ERR) {
  34.         remark_("wrong mode in acopy",19L);
  35.         return;
  36.     }
  37.  
  38.     /* move the characters */
  39.     for(i=1; i <= *size && (c=getch_(&c,fdi)) != EOF ; i++)
  40.          putch_(&c,fdo);
  41.  
  42. }
  43.  
  44. cant_(name)
  45. int *name;
  46.  
  47. {
  48.     /* outputs the message 'CANT OPEN FILE OF NAME: ' name on stderr */
  49.  
  50.     int fd = STDERR, newline = NEWLINE;
  51.  
  52.     zchout_("CAN'T OPEN FILE OF NAME: ", &fd, 25L);
  53.     putlin_(name, &fd);
  54.     putch_(&newline, &fd);
  55.  
  56. }
  57.  
  58. close_(fd)
  59. int *fd;
  60.  
  61. {
  62.     /* Terminate access to the file descriptor fd. This
  63.        routine may be used on both sequential and direct
  64.        access files.
  65.  
  66.        Attempting to close a preconnected file or a closed file
  67.        has no effect */
  68.  
  69.     struct fdinfo *ptr;
  70.  
  71.     if( checkfd(*fd) != FILES)
  72.      /*    no effect on preconnected units */
  73.         return;
  74.  
  75.     ptr = &files[*fd];
  76.  
  77.     /* deal with no effect cases */
  78.  
  79. /*    if ( ptr->access == NOTOPEN)
  80.           return;   */
  81.  
  82.     /* set access to NOTOPEN, write out the current buffer if
  83.        currentaccess is write and close the file */
  84.  
  85.     ptr->access = NOTOPEN;
  86.     flush(*fd);
  87.     close(*fd);
  88. if(DEBUG) printf("in close : just closed fd = %d\n",*fd);
  89. }
  90.  
  91. create_( name, access)
  92. int *name, *access;
  93.  
  94. {
  95.     /* create a sequential file of name name and open it with
  96.        access type access. Assign an internal file descriptor
  97.        to the file and return this via the function name. If
  98.        a file already exists with this name it is deleted
  99.        prior to creation */
  100.  
  101.         int uid,gid,len,i;
  102.         char newch[MAXPATH];
  103.         struct stat sbuf;
  104.  
  105.     int fd, pmode;
  106.     char charnm1[MAXPATH];
  107.     struct fdinfo *ptr;
  108.     struct filinfo openinf;
  109.  
  110.      /*    generate full path name as a character string */
  111.         mkfilnm(name, charnm1, &openinf);
  112.  
  113.      /*    sort out possible error cases */
  114.     switch (openinf.ftype1)
  115.     {
  116.       case ERR:  /* error in mkpath or host file a directory */
  117.         return(ERR);
  118.     
  119.       case DEVICE: /* return err for illegal access otherwise fd */
  120.         return((prconfl(openinf.subtype, *access) == ERR)
  121.             ? ERR : openinf.subtype);
  122.  
  123.       case VFS:  /* error if directory */
  124.         if(openinf.subtype == DIRECTORY)
  125.             return(ERR);
  126.      }
  127.     /* SHOULD WE CHECK WHETHER FILE IS ALREADY OPEN ??? */
  128.  
  129.     pmode = RWMODE;
  130.  
  131.     /* attempt to create file - if file already exists it will be
  132.        truncated to length zero */
  133.     fd = creat(charnm1, pmode);
  134.  
  135.  
  136. if(DEBUG) printf("in create after creat : file = <%s> : fd = %d\n",charnm1,fd);
  137.     /* return the file descriptor if fd > MAXFD */
  138.     if(fd > MAXFD) {
  139.         close(fd);
  140.         
  141. if(DEBUG) printf("in create after close1 : file = <%s> : fd = %d\n",charnm1,fd);
  142.         /* remove zero length file */
  143.         unlink(charnm1);
  144.         return(ERR);
  145.     }
  146.  
  147.     /* return if not created */
  148.     if (fd == -1 )
  149.          return(ERR);
  150.  
  151.     /* reopen with mode access */
  152.     close(fd);
  153. if(DEBUG) printf("in create after close2 : file = <%s> : fd = %d\n",charnm1,fd);
  154.     fd = open(charnm1, *access);
  155. if(DEBUG) printf("in create after open : file = <%s> : fd = %d\n",charnm1,fd);
  156.  
  157.     /* opened - initialize file descriptor block */
  158.     ptr = &files[fd];
  159.     strcpy(files[fd].filenam, charnm1);
  160.     ptr -> access = *access;
  161.     
  162.     /* initialize current access to WRITE if write or readwrite
  163.     access requested, READ if read access requested */
  164.     if (*access == READ)
  165.         ptr->caccess = READ;
  166.     else
  167.         ptr->caccess = WRITE;
  168.     ptr -> bufp = ptr -> buffer;
  169.     ptr -> chrleft = 0;
  170.     return (fd) ;
  171.  
  172. }
  173.  
  174. error_(string, length)
  175. char *string;
  176. long int length;
  177.  
  178. {
  179.     /* output an error message string to stderr and terminate the
  180.        tool with a call to ZQUIT with status ZERR */
  181.  
  182.     int err = ERR;
  183.  
  184.     remark_(string, length);
  185.     zquit_( &err );
  186.  
  187. }
  188.  
  189. getc_(ch)
  190. int *ch;
  191.  
  192. {
  193.  
  194.     /* get a single character from the standard input*/
  195.  
  196.     int fd = STDIN;
  197.  
  198.     return ( *ch = getch_(ch, &fd) );
  199.  
  200. }
  201.  
  202.  
  203. getch_(ch, fd)
  204. int *ch, *fd;
  205.  
  206. {
  207.  
  208.     /* get a single character from the sequential fle
  209.        with file descriptor fd. Trailing blanks i.e.
  210.        those between the last non-space and the final
  211.        newline are stripped out */
  212.  
  213.     struct fdinfo *ptr;
  214.     char c;
  215.  
  216.     /* check for valid fd and file open in read mode */
  217.     if ( opnread(*fd) == ERR )
  218.         return( *ch = ERR );
  219.  
  220.     ptr = &files[*fd];
  221.  
  222.     /* still embedded spaces to pass on ? */
  223.     if (ptr->count > 0) {
  224.         ptr->count--;
  225.         return( *ch = BLANK);
  226.     }
  227.  
  228.  
  229.     /* file open in read mode now */
  230.  
  231.     if (ptr->chrleft == 0) {
  232.  
  233.     /* buffer is empty */
  234.         ptr->chrleft = read(*fd, ptr->buffer, BLOCKSIZE);
  235.         ptr->bufp = ptr->buffer;
  236.     
  237.         /* return EOF if no characters read */
  238.         if (ptr->chrleft == 0) {
  239.             /* throw away spaces if no newline before EOF */
  240.             ptr->count = 0;
  241.             return( *ch = EOF);
  242.         }
  243.     }
  244.     
  245.     /* eat white space refilling the buffer as necessary */
  246.     while ((c = *ptr->bufp++) == BLANKCH) {
  247.         ptr->count++;
  248.         ptr->chrleft--;
  249.  
  250.         if (ptr->chrleft == 0){
  251.             /* if we run out of characters refill the buffer */
  252.             ptr->chrleft = read(*fd, ptr->buffer, BLOCKSIZE);
  253.             ptr->bufp = ptr->buffer;
  254.         
  255.             /* return EOF if no characters read */
  256.             if (ptr->chrleft == 0) {
  257.                 /* throw away spaces if no newline before EOF */
  258.                 ptr->count = 0;
  259.                 return( *ch = EOF);
  260.             }
  261.         }
  262.     }
  263.  
  264.     /* we now have a non-space character and ptr->bufp is pointing
  265.        at the next character although ptr->chrleft hasn't included
  266.        this */
  267.     if (c == NEWLINECH){
  268.         /* possibly training blanks - pointer already on
  269.         next character */
  270.         ptr->count = 0;
  271.         ptr->chrleft--;
  272.         return(*ch = NEWLINE);
  273.     }
  274.     else if (ptr->count == 0) {
  275.         /* decrement count and return character */
  276.         ptr->chrleft--;
  277.         *ch = zcctoi_(&c, ch);
  278.         return(*ch);
  279.     }
  280.     else {
  281.     /* embedded spaces - return a space and decrement space count.
  282.        Backtrack pointer to next non space char, leave the character
  283.        counter alone */
  284.         ptr->bufp--;
  285.         ptr->count--;
  286.         return(*ch = BLANK);
  287.     }
  288. }
  289.  
  290. getlin_(buffer, fd)
  291. int *buffer, *fd;
  292.  
  293. {
  294.     /* geta line from the sequential file associated with
  295.        the file descriptor fd. The number of characters
  296.        read into buffer including the newline but not the
  297.        eos is returned. If eof was encountered on fd then
  298.        eof is returned. The number of characters read into
  299.        buffer never exceeds maxline although a newline and eos
  300.        may be appended making the maximum length of buffer
  301.        maxbuff */
  302.  
  303.     int i, c;
  304.     
  305.     /* get a line */
  306.     for (i = 1; i <= MAXLINE && (c=getch_(&c,fd)) != NEWLINE && c != EOF
  307.             && c != ERR; *buffer++ = c , i++ );
  308.  
  309.     /* already have maxline characters without a newline */
  310.     if (i > MAXLINE) {
  311.         /* flush the newline or lose character MAXLINE +1 */
  312.         c = getch_(&c, fd);
  313.         *buffer++ = NEWLINE;
  314.         *buffer = EOS;
  315.         return(MAXLINE + 1);
  316.     }
  317.  
  318.     switch (c) {
  319.  
  320.         case NEWLINE:
  321.             *buffer++ = NEWLINE;
  322.             *buffer = EOS;
  323.             return(i);
  324.  
  325.         case EOF:
  326.             *buffer++ = NEWLINE;
  327.             *buffer = EOS;
  328.             return(EOF);
  329.  
  330.         case ERR:
  331.             *buffer = EOS;
  332.             return(ERR);
  333.  
  334.     }
  335. }
  336.  
  337.  
  338. open_(name, access)
  339. int *name, *access;
  340. {
  341.     /* open an existing sequential file name with access type
  342.        access (=r, w or rw). Assign an internal file descriptor
  343.        and return it as the value of the function. It is illegal
  344.        to try and open a file which does not exist */
  345.  
  346.     int fd;
  347.     struct filinfo openinf;
  348.     char charnm1[MAXPATH];
  349.  
  350.      /*    generate full path name as a character string */
  351.         mkfilnm(name, charnm1, &openinf);
  352.  
  353.      /*    sort out possible error cases */
  354.     switch (openinf.ftype1)
  355.     {
  356.       case ERR:  /* error in mkpath or host file a directory */
  357.         return(ERR);
  358.     
  359.       case DEVICE: /* return err for illegal access otherwise fd */
  360.         return((prconfl(openinf.subtype, *access) == ERR)
  361.             ? ERR : openinf.subtype);
  362.  
  363.       case HOST:  /* error if file doesn't exist */
  364.         if(openinf.exists == NO) return(ERR);
  365.         break;
  366.  
  367.       case VFS:  /* error if file doesn't exist or directory */
  368.         if(openinf.exists == NO || openinf.subtype == DIRECTORY)
  369.             return(ERR);
  370.      }
  371.         
  372.     /* ensure open ok and not too many descriptors */
  373.     if((fd=open(charnm1, *access)) == -1 ) return(ERR);
  374.  
  375. if(DEBUG) printf("in open : file = <%s> : fd = %d\n",charnm1,fd);
  376.     if (fd > MAXFD) {
  377.         close(fd);
  378. if(DEBUG) printf("in open after close1 : file = <%s> : fd = %d\n",charnm1,fd);
  379.         return(ERR);
  380.     }
  381.  
  382.     /* store file info and initialize buffers etc. */
  383.     strcpy(files[fd].filenam, charnm1);
  384.     files[fd].ftype = SEQUENTIAL;
  385.     files[fd].access = *access;
  386.  
  387.     /* set current access to READ if access is read or readwrite
  388.     and to WRITE if access is write */
  389.     if (*access == WRITE)
  390.         files[fd].caccess = WRITE;
  391.     else
  392.         files[fd].caccess = READ;
  393.  
  394.         files[fd].chrleft = 0;
  395.     files[fd].bufp = files[fd].buffer;
  396.     return(fd);
  397.  
  398. }
  399.  
  400. /* void */
  401. putc_(ch)
  402. int *ch;
  403.  
  404. {
  405.     /* put a character out on the standard output file stdout */
  406.     int fd = STDOUT;
  407.     putch_(ch, &fd);
  408.  
  409.  
  410. }
  411.  
  412.  
  413. putch_(ch, fd)
  414. int *ch, *fd;
  415.  
  416. {
  417.  
  418.     /* put a character out to a sequential file with
  419.            file descriptor fd. Output is buffered until
  420.            the buffer is full or the program terminates */
  421.  
  422.     struct fdinfo *ptr;
  423.  
  424.     /* check for valid fd and file open in write mode */
  425.     if ( opnwrit( *fd ) == ERR )
  426.         return;
  427.  
  428.     ptr = &files[*fd];
  429.  
  430.     /* file open in write mode now */
  431.  
  432.     if (ptr->chrleft == MAXLINE) {
  433.  
  434.     /* buffer is full append newline and flush */
  435.         *ptr->bufp = NEWLINE;
  436.         ptr->chrleft++;
  437.  
  438.     /* delete any trailing spaces before NEWLINE */
  439.         ptr->chrleft = fndnblk(ptr->bufp, ptr->chrleft);
  440.  
  441.     /* and write out the buffer */
  442.         write(*fd, ptr->buffer, ptr->chrleft);
  443.         ptr->chrleft = 0;
  444.         ptr->bufp = ptr->buffer;
  445.         /* if current character a NEWLINE then return as it
  446.            has already been output */
  447.         if (*ch == NEWLINE) return;
  448.     }
  449.  
  450.     /* store character in buffer */
  451.     *ptr -> bufp ++ = *ch;
  452.     ptr->chrleft ++;
  453.  
  454.      /*    flush buffers on a newline */
  455.     if (*ch == NEWLINE) {
  456.     /* delete any trailing spaces before NEWLINE */
  457.         ptr->bufp--;
  458.         ptr->chrleft = fndnblk(ptr->bufp, ptr->chrleft);
  459.         write(*fd, ptr->buffer, ptr -> chrleft);
  460.         ptr->chrleft = 0;
  461.         ptr->bufp = ptr->buffer;
  462.  
  463.     }
  464. }
  465.  
  466.  
  467. putdec_( value, width)
  468. int *value, *width;
  469.  
  470. {
  471.     /* write the number value out to stdout in a field of width
  472.        width. If the length of the number as a string is <=
  473.        width it is blank filled right justified, else the number
  474.        is output in a wider field */
  475.  
  476.     int fd = STDOUT;
  477.  
  478.     zptint_(value, width, &fd);
  479.  
  480. }
  481.  
  482. putlin_(buffer, fd)
  483. int *buffer, *fd;
  484.  
  485. {
  486.     /* output the string in buffer (terminated by eos) to
  487.        the file associated with the file descriptor fd */
  488.  
  489.     int c;
  490.  
  491.     while ((c = *buffer++) != EOS)
  492.         putch_(&c, fd);
  493.  
  494. }
  495.  
  496.  
  497. readf_( buf, count, fd)
  498. int *buf, *count, *fd;
  499.  
  500. {
  501.     /* read count characters from the file with associated
  502.        file descriptor fd into buf and terminate with an
  503.        EOS character. This routine has no way of indicating
  504.        a read past end of file.
  505.  
  506.        WARNING: use GETLIN or ZGTCMD in preference */
  507.  
  508.     int i, c;
  509.  
  510.     for (i = 1; i <= *count && (*buf++ = getch_(&c, fd)) != EOF; i++);
  511.  
  512.     if (c == EOF )
  513.         buf--;
  514.  
  515.     *buf = EOS;
  516.  
  517. }
  518.  
  519. remark_(s, length)
  520. char *s;
  521. long int length;
  522.  
  523. {
  524.     /* output an f77 string up to but not including a terminating
  525.        PERIOD to STDERR. If no terminating period all length
  526.        characters are output. A period within a string is denoted
  527.        by '..' */
  528.  
  529.     int fd = STDERR, newline = NEWLINE;
  530.     struct fdinfo *ptr;
  531.  
  532.     /* make sure that STDERR is OK to write to. This is done in
  533.     putch but if things get screwed there is the possibility of
  534.     an endless call putch loop - the next statement is a panic
  535.     exit */
  536.     ptr = &files[STDERR];
  537.     
  538.     if (ptr->access == NOTOPEN || ptr->access == READ) exit(1);
  539.  
  540.     /* if the above checks are OK the following putch's should be
  541.     ok i.e. they won't result in another call to remark */
  542.  
  543.     zchout_(s, &fd, length);
  544.     putch_( &newline, &fd);
  545.  
  546. }
  547.  
  548. remove_(name)
  549. int *name;
  550. {
  551.  
  552.      /* delete the closed file name from the directory. This routine
  553.     may be used to remove either a sequential or a direct access
  554.     file */
  555.  
  556.     int fd;
  557.     char charnm1[MAXPATH];
  558.     struct fdinfo *ptr;
  559.     struct filinfo openinf;
  560.  
  561.     mkfilnm(name, charnm1, &openinf);
  562.  
  563.     /* can't remove device file and return on filename error */
  564.     switch (openinf.ftype1)
  565.     {
  566.       case ERR:
  567.         return;
  568.  
  569.       case DEVICE:
  570.         return;
  571.  
  572.       case VFS :
  573.         if (openinf.subtype == DIRECTORY) return;
  574.         break;
  575.  
  576.     }
  577.     /* if it doesn't exist there's no need to delete it */
  578.     if (openinf.exists != YES) return;
  579.  
  580.     /* close the file if it is open */
  581.     for (fd = FIRSTFD; fd < MAXFILE; fd++)
  582.     {    ptr = &files[fd];
  583.         if (ptr->access != NOTOPEN && strcmp( ptr -> filenam, charnm1) == 0)
  584.             close_(&fd);
  585.     }
  586.     
  587.     /* remove the file */
  588.     unlink(charnm1);
  589.     return;
  590.  
  591. }
  592.  
  593. seek_(pos, fd)
  594. int *pos, *fd;
  595. {
  596.     /* despite what the documentation says this routine
  597.        effects a rewind on channel fd.
  598.        It has no effect on preconnected files */
  599.  
  600.         struct fdinfo *ptr;
  601.  
  602.         ptr = &files[*fd];
  603.  
  604.     if (checkfd(*fd) != FILES || files[*fd].access == NOTOPEN)
  605.            return;
  606.  
  607.     /* move the file pointer back to the begining of the file */
  608.         ptr -> chrleft = 0;
  609.         ptr -> count = 0;
  610.         ptr -> bufp = ptr ->buffer;
  611.     lseek(*fd,(long)(*pos),0);
  612.  
  613.  
  614. }
  615.  
  616. skip_(lines)
  617. int *lines;
  618.  
  619. {
  620.     /* output lines blank lines to stdout */
  621.  
  622.     int i, newline = NEWLINE, fd = STDOUT;
  623.  
  624.     for(i = 1; i <= *lines; i++)
  625.           putch_( &newline, &fd);
  626.  
  627. }
  628.  
  629. zbcret_(name, maxrec)
  630. int *name, *maxrec;
  631. {
  632.  
  633.      /* create a direct access file with a maximum of MAXREC records
  634.     The file is to contain fixed length records of length MAXBUFF.
  635.     Any existing file, name, is deleted (truncated to length zero).
  636.     
  637.     The first record in the file is to contain the maximum record
  638.     number.
  639.     
  640.     The file descriptor is returned or ERR if create fails. */
  641.  
  642.         int uid,gid,len,i;
  643.         char newch[MAXPATH];
  644.         struct stat sbuf;
  645.  
  646.  
  647.     struct fdinfo *ptr;
  648.     struct filinfo openinf;
  649.     char charnm1[MAXPATH];
  650.     int fd, junk, iststr[MAXBUFF];
  651.     int access = READWRITE;
  652.  
  653.      /*    generate full path name as a character string */
  654.         mkfilnm(name, charnm1, &openinf);
  655.  
  656.      /*    sort out possible error cases */
  657.     switch (openinf.ftype1)
  658.     {
  659.       case ERR:  /* error in mkpath or host file a directory */
  660.         return(ERR);
  661.     
  662.       case DEVICE: /* return err for illegal access otherwise fd */
  663.         return((prconfl(openinf.subtype, access) == ERR)
  664.             ? ERR : openinf.subtype);
  665.  
  666.       case VFS:  /* error if directory */
  667.         if(openinf.subtype == DIRECTORY)
  668.             return(ERR);
  669.      }
  670.     /* SHOULD WE CHECK WHETHER FILE IS ALREADY OPEN ??? */
  671.  
  672.  
  673.  
  674.     /* attempt to create file - if file already exists it will be
  675.        truncated to length zero */
  676.     fd = creat(charnm1, RWMODE);
  677.  
  678.     /* return the file descriptor if fd > MAXFD */
  679.     if(fd > MAXFD) {
  680.         close(fd);
  681.         /* remove zero length file */
  682.         unlink(charnm1);
  683.         return(ERR);
  684.     }
  685.  
  686.     /* return if not created */
  687.     if (fd == -1 )
  688.          return(ERR);
  689.     /* close and reopen in readwrite mode */
  690.     close(fd);
  691.     fd = open(charnm1, READWRITE);
  692.  
  693.     /* set up file descriptor block */
  694.     ptr = &files[fd];
  695.     ptr->bufp = ptr->buffer;
  696.     ptr->ftype = DIRECT;
  697.     ptr->chrleft = *maxrec;
  698.     ptr->access = READWRITE;
  699.     strcpy(ptr->filenam, charnm1);
  700.  
  701.     /* write maximum number of records to first record of file */
  702.     junk = MAXBUFF;
  703.     itoc_(maxrec, &iststr[0], &junk);
  704.     
  705.      /* switch on access to record zero */
  706.     opnrec0 = 1;
  707.  
  708.     /* put the first record into the file */
  709.     junk = 0;
  710.     zbputr_(&fd, &junk, &iststr[0]);
  711.  
  712.     /* switch off access to record 0 */
  713.     opnrec0 = 0;
  714.     /* return the file descriptor */
  715.     return(fd);
  716.  
  717. }
  718.  
  719. zbgetr_(fd, recnum, buf)
  720. int *fd, *recnum, *buf;
  721. {
  722.  
  723.      /* read the contents of record number recnum from the direct access file
  724.         associated with the file descriptor fd into buf.
  725.         It is an error to use a invalid recnum or attempt
  726.         to access a sequential file. buf must be of size MAXBUFF
  727.         to prevent the overwriting of data areas.
  728.         Reading a record that has not previously been written will
  729.         result in a buf vector filled with nulls */
  730.  
  731.         struct fdinfo *ptr;
  732.         unsigned char  ch;
  733.         char *ptc;
  734.         int junk, i;
  735.         long int recpos;
  736.  
  737.      /* check file descriptor is FILES ie not out of range
  738.         or one of the preconnected units and associated file is open */
  739.         if (checkfd(*fd) != FILES || files[*fd].access == NOTOPEN) return(ERR);
  740.  
  741.         /* check file open for direct access */
  742.         if (files[*fd].ftype != DIRECT) return(ERR);
  743.  
  744.         /* check record number is in range */
  745.         /* opnrec0 = 1 allows access to record zero only this
  746.            is only set by zbopen */
  747.         if (opnrec0 == 0 && chkrnum(*recnum, *fd) == ERR) return(ERR);
  748.  
  749.         ptr = &files[*fd];
  750.         ptc = ptr -> buffer;
  751.  
  752.         /* find the required position in the file */
  753.         recpos = *recnum * MAXBUFF;
  754.         lseek(*fd, recpos, 0);
  755.  
  756.         /* read into fdinfo buffer */
  757.         read(*fd, ptr->buffer, MAXBUFF);
  758.  
  759.         /* and convert each character to its equivalent IST character  */
  760.         for (i=0; i<MAXBUFF; i++){
  761.         /* don't interpret the sign bit as a sign !! */
  762.                  ch = *ptc++;
  763.                  *buf++ = ch;
  764.         }
  765.  
  766.         return(NOERR);
  767.  
  768. }
  769.  
  770. zbopen_(name, maxrec)
  771. int *name, *maxrec;
  772. {
  773.  
  774.      /* open a preexisting direct access file and return the maximum
  775.     record number allowed. The file is for fixed length (MAXBUFF)
  776.     formatted records.
  777.     The maximum record number is stored in the first record in the
  778.     file. Direct access files are always opened/created in
  779.     READWRITE MODE */
  780.  
  781.     struct filinfo openinf;
  782.     char charnm1[MAXPATH];
  783.     int fd, temp;
  784.     int buffer[MAXBUFF];  /* local buffer used for storing value of maxrec */
  785.     int access = READWRITE;
  786.  
  787.      /*    generate full path name as a character string */
  788.         mkfilnm(name, charnm1, &openinf);
  789.  
  790.      /*    sort out possible error cases */
  791.     switch (openinf.ftype1)
  792.     {
  793.       case ERR:  /* error in mkpath or host file a directory */
  794.         return(ERR);
  795.     
  796.       case DEVICE: /* return err for illegal access otherwise fd */
  797.         return((prconfl(openinf.subtype, access) == ERR)
  798.             ? ERR : openinf.subtype);
  799.  
  800.       case HOST:  /* error if file doesn't exist */
  801.         if(openinf.exists == NO) return(ERR);
  802.         break;
  803.  
  804.       case VFS:  /* error if file doesn't exist or directory */
  805.         if(openinf.exists == NO || openinf.subtype == DIRECTORY)
  806.             return(ERR);
  807.      }
  808.         
  809.     /* ensure file exists and not too many descriptors */
  810.     if((fd=open(charnm1, READWRITE)) == -1 ) return(ERR);
  811.     if (fd > MAXFD) {
  812.         close(fd);
  813.         return(ERR);
  814.     }
  815.  
  816.     /* store file info */
  817.     strcpy(files[fd].filenam, charnm1);
  818.     files[fd].ftype = DIRECT;
  819.     files[fd].access = READWRITE;
  820.  
  821.  
  822.     /* switch on access to record zero */
  823.     opnrec0 = 1;
  824.  
  825.     /* get first record, return value of maxrec and store it for
  826.        future gets and puts in chrleft */
  827.     temp = 0;
  828.     zbgetr_(&fd, &temp, &buffer[0]);
  829.     temp = 1;
  830.  
  831.     /* switch off access to record zero */
  832.     opnrec0 = 0;
  833.     /* a value of zero probably indicates access of a sequential file */
  834.     if( (*maxrec = ctoi_(&buffer[0], &temp)) == 0) {
  835.         close(fd);
  836.         return(ERR);
  837.     }
  838.     files[fd].chrleft = *maxrec;
  839.     
  840.     return(fd);
  841. }
  842.  
  843. zbputr_(fd, recnum, buf)
  844. int *fd, *recnum, *buf;
  845. {
  846.  
  847.      /* write the contents of buf to the direct access file
  848.         associated with the file descriptor fd at record number
  849.         recnum. It is an error to use a invalid recnum or attempt
  850.         to access a sequential file. buf must be of size MAXBUFF
  851.         and may contain any valid IST characters including embedded
  852.         EOS and NEWLINE characters. Any value in buf outside the
  853.         range 0-255 will be stored as zero */
  854.  
  855.         struct fdinfo *ptr;
  856.         char *ptc;
  857.         int c, i;
  858.         long int recpos;
  859.  
  860.      /* check file descriptor is FILES ie not out of range
  861.         or one of the preconnected units and associated file is open */
  862.         if (checkfd(*fd) != FILES || files[*fd].access == NOTOPEN) return(ERR);
  863.  
  864.         /* check file open for direct access */
  865.         if (files[*fd].ftype != DIRECT) return(ERR);
  866.  
  867.         /* check record number is in range */
  868.         /* unless permission to access record zero is set */
  869.         if ( opnrec0 == 0 && chkrnum(*recnum, *fd) == ERR) return(ERR);
  870.  
  871.         ptr = &files[*fd];
  872.         ptc = ptr -> buffer;
  873.  
  874.         /* find the required position in the file */
  875.         recpos = *recnum * MAXBUFF;;
  876.         lseek(*fd, recpos, 0);
  877.  
  878.         /* write IST string to fdinfo buffer */
  879.         for (i=0; i<MAXBUFF; i++)
  880.         {
  881.                 if ( (c = *buf++) > 255 || c < 0) c = 0;
  882.                 *ptc++ = c;
  883.         }
  884.  
  885.         /* and thence to the file */
  886.         write(*fd, ptr->buffer, MAXBUFF);
  887.  
  888.         return(NOERR);
  889.  
  890. }
  891.  
  892. zchout_(s, fd, length)
  893. char *s;
  894. int *fd;
  895. long int length;
  896.  
  897. {
  898.     /* output an f77 string terminated by a period to the file associated
  899.        with the file descriptor fd.  No trailing NEWLINE is appended to
  900.        the line and the period is not transmitted.  A period within the
  901.        string is denoted by '..' */
  902.  
  903.     char *ptr ;
  904.     char period = PERIODCH;
  905.  
  906.     /* set pointer to end of string */
  907.  
  908.     ptr = s+length-1;
  909.  
  910.     /* loop through the string */
  911.  
  912.     while (s < ptr)
  913.     {
  914.         /* take care of double period case */
  915.         if( *s == PERIODCH && *(s+1) == PERIODCH )
  916.         {
  917.             zputch_( &period, fd);
  918.             s += 2;
  919.         }
  920.  
  921.         /* single PERIOD - return */
  922.         else if (*s == PERIODCH)
  923.             return;
  924.  
  925.         /* else output the character */
  926.         else
  927.             zputch_(s++, fd);
  928.     }
  929.  
  930.     /* deal with last character either PERIOD (ignore)
  931.            or character (output) */
  932.     if(*ptr != PERIODCH)
  933.         zputch_( ptr,fd);
  934.  
  935. }
  936.  
  937. zcntrl_(fd, leni, leno, flag)
  938. int *fd, *leni, *leno, *flag;
  939. {
  940.  
  941.     /* Change the handling of input and output strings for all future
  942.        sequential i/o with associated file descriptor fd. Allows the
  943.        user to control the input record length, the output record length,
  944.        and the backspace processing for each channel. Backspace
  945.        processing consists of checking each line for backspaces
  946.        and removing both them and the preceding charcater, i.e. treating
  947.        them as character deletes. Any invalid argument values are
  948.        ignored and result in no change to that parameter */
  949.  
  950.        remark_("Routine ZCNTRL not implemented in this version of TIE",53L);
  951. }
  952.  
  953. zcrdir_(name)
  954. int *name;
  955. {
  956.  
  957.      /* create a new directory with name name in the local directory.
  958.     No path names are allowed
  959.     The name name must be unique in this directory */
  960.  
  961.     int mode = RWXMODE;
  962.     char charnm1[MAXPATH];
  963.     struct filinfo finf;
  964.  
  965.     /* create character file name and check it is a simple name */
  966.     istchr_(name, charnm1);
  967.     if (isaname(charnm1) == NO) return(ERR);
  968.  
  969.     /* generate full path name */
  970.     mkfilnm(name,charnm1,&finf);
  971.  
  972.     /* return if name exists, name is a device or name is erroneous */
  973.  if (finf.exists == YES || finf.ftype1 == DEVICE || finf.ftype1 == ERR)
  974.             {
  975.         return(ERR);
  976.             }
  977.  
  978.     /* system call */
  979.     if (mkdir(charnm1, mode) == -1) return(ERR);
  980.  
  981.     return(NOERR);
  982.  
  983. }
  984.  
  985. zdldir_(name)
  986. int *name;
  987. {
  988.  
  989.      /* delete an empty directory with name name in the local directory. */
  990.  
  991.     char charnm1[MAXPATH];
  992.     struct filinfo finf;
  993.  
  994.     /* create character file name and check it is a simple name */
  995.     istchr_(name, charnm1);
  996.     if (isaname(charnm1) == NO) return(ERR);
  997.  
  998.     /* generate a full path name */
  999.     mkfilnm(name, charnm1, &finf);
  1000.  
  1001.     /* return if not a directory */
  1002.     if (finf.subtype != DIRECTORY) return(ERR);
  1003.  
  1004.     /* disallow deletion of root and root/ */
  1005.     if (strcmp(root, charnm1)==0 ||
  1006.         strcmp(strcat(root,"/"), charnm1)==0 ) return(ERR);
  1007.  
  1008.     /* system call */
  1009.     if (rmdir(charnm1) == -1) return(ERR);
  1010.  
  1011.     return(NOERR);
  1012.  
  1013. }
  1014.  
  1015. zftype_(name, sequen)
  1016. int *name, *sequen;
  1017. {
  1018.  
  1019.     /* Discover the type of the entity with the pathname name.
  1020.        This routine returns ERR (file does not exist or illegal
  1021.        file name), host, device (preconnected unit), plain
  1022.        (vfs file) or directory (vfs directory) */
  1023.  
  1024.     struct filinfo finf;
  1025.     char charnm1[MAXPATH];
  1026.  
  1027.     /* on UNIX the file is always sequential */
  1028.     *sequen = YES;
  1029.  
  1030.     mkfilnm(name, charnm1, &finf);
  1031.  
  1032.     /* deal with the error case first */
  1033.     if (finf.ftype1 == ERR || finf.exists == NO) return(ERR);
  1034.  
  1035.     /* vfs file */
  1036.     if (finf.ftype1 == VFS) return(finf.subtype);
  1037.  
  1038.     /* host files or devices */
  1039.     return(finf.ftype1);
  1040. }
  1041.  
  1042. zgetch_(c,fd)
  1043. char *c;
  1044. int *fd;
  1045. {
  1046.     /* get an f77 character from the sequential file associated
  1047.        with the file descriptor fd and return it in c. The IST
  1048.        equivalent value is returned via the function name */
  1049.  
  1050.     int inch;
  1051.     char ch;
  1052.  
  1053.     inch = getch_(&inch, fd);
  1054.     if(inch != EOF && inch != ERR)
  1055.         zcitoc_(c, 1L, &inch, &ch);
  1056.  
  1057.     return(inch);
  1058.  
  1059. }
  1060.  
  1061. zgetln_(buf, fd)
  1062. char *buf;
  1063. int *fd;
  1064. {
  1065.     /* get an f77 character string from the sequential file
  1066.        associated with the file descriptor fd and return it
  1067.        in buf. The number of valid characters in the string
  1068.        is returned through the function. The string may or
  1069.        may not be terminated by an odd number of '.' as required
  1070.        by ZCHOUT and ZMESS */
  1071.  
  1072.     char ch;
  1073.     int val, i;
  1074.  
  1075.     /* read characters until a newline, end of file, error or
  1076.        maxbuff characters read */
  1077.     for(i = 1; i<=MAXBUFF && (val = zgetch_(&ch, fd)) != NEWLINE
  1078.                && val != EOF && val != ERR ; *buf++ = ch , i++) ;
  1079.  
  1080.     /* return the length of the string or the error or end of
  1081.        file value */
  1082.     return ((val==EOF || val==ERR) ? val : i-1);
  1083.  
  1084. }
  1085.  
  1086. zgtcmd_(arg, fd)
  1087. int *arg, *fd;
  1088.  
  1089. {
  1090.     /* get a line of information from the file associated
  1091.        with the file descriptor fd using getlin. Strip off
  1092.        the trailing NEWLINE and return the length of the
  1093.        resulting string ( or ERR or EOF) */
  1094.  
  1095.     int n;
  1096.  
  1097.     n = getlin_(arg, fd);
  1098.  
  1099.     /* order of evaluation guaranteed left to right */
  1100.  
  1101.     if ( n != ERR && n != EOF && *(arg+n-1) == NEWLINE)
  1102.           *(arg + --n) = EOS;
  1103.     return ( n );
  1104.  
  1105. }
  1106.  
  1107. zinstr_(str, n, fd)
  1108. int *str, *n, *fd;
  1109. {
  1110.  
  1111.     /* read a line of n IST characters into the array str from
  1112.        the file associated with the file descriptor fd.
  1113.  
  1114.        If n<=0 read up to and including the first NEWLINE
  1115.           if no characters can be read return a single NEWLINE
  1116.  
  1117.        If n>0 return the first n characters - there is no
  1118.        guarantee that the last character will be a NEWLINE
  1119.  
  1120.     WARNING : Use GETLIN or ZGTCMD in preference */
  1121.  
  1122.     int i, c;
  1123.  
  1124.     /* n positive */
  1125.  
  1126.     if ( *n > 0)
  1127.     {
  1128.         for (i = 1; i <= *n && (c=getch_(&c, fd)) != ERR && c != EOF;
  1129.                   i++)
  1130.             *str++ = c;
  1131.         if (c == ERR)
  1132.             return(ERR);
  1133.         else
  1134.             return(i-1);
  1135.     }
  1136.  
  1137.     /* n negative - while loop takes care of EOF on first character */
  1138.  
  1139.     i = 0;
  1140.     while ((c = getch_(&c, fd)) != NEWLINE && c != EOF && c != ERR)
  1141.     {
  1142.         i++;
  1143.         *str++ = c;
  1144.     }
  1145.     
  1146.     if ( c == ERR)
  1147.         return(ERR);
  1148.  
  1149.     *str++ = NEWLINE;
  1150.     *str = EOS;
  1151.     
  1152.     return(i+1); /* includes the NEWLINE character */
  1153.  
  1154. }
  1155.  
  1156.  
  1157. zlocal_(name)
  1158. int *name;
  1159. {
  1160.  
  1161.     /* change the local directory to that specified by name. Resets
  1162.        the directory reading pointer to the start of the local
  1163.        directory entry table. If name is null the root is selected */
  1164.  
  1165.     char charnm1[MAXPATH], temp[MAXPATH];
  1166.     char *ptr;
  1167.     struct filinfo finf;
  1168.     int status;
  1169.     DIR *opendir();
  1170.  
  1171.     /* set global directory read error flag */
  1172.     direrr = NOERR;
  1173.     /* deal with null name and "/" */
  1174.     if (*name == EOS || ( *name == SLASHCH && *(name+1) == EOS)) {
  1175.         strcpy(lcldir, "");
  1176.         /* open the root directory */
  1177.     /* close directory stream if one open before opening a new one */
  1178.         if (dirp != (DIR*) NULLST)closedir(dirp);
  1179.         dirp = opendir(root);
  1180.         if (dirp == (DIR*) NULLST) direrr = ERR;
  1181.     }
  1182.     
  1183.     else {
  1184.         istchr_(name, temp);
  1185.         /* convert pathname to lower case and strip
  1186.            leading white space */
  1187.         for (ptr = temp; *ptr == BLANKCH || *ptr == TABCH ;ptr++);
  1188.         while (*ptr != EOSCH) {
  1189.             *ptr = ( isupper(*ptr) ? tolower(*ptr) : *ptr );
  1190.             ptr++;
  1191.         }
  1192.         if ((status = mkpath(temp, charnm1)) == ERR) return(ERR);
  1193.  
  1194.         /* check path exists and is a directory */
  1195. if(DEBUG)printf(" in zlocal - charnm1 = %s\n",charnm1);
  1196.         if (isadir(charnm1) == NO) return(ERR);
  1197. if(DEBUG)printf(" in zlocal isadir returns %d\n",isadir(charnm1));
  1198.  
  1199.  
  1200.         /* open directory stream */
  1201.     /* close directory stream if one open before opening a new one */
  1202.         if (dirp != (DIR*) NULLST)closedir(dirp);
  1203.         dirp = opendir(charnm1);
  1204.         if (dirp == (DIR*) NULLST)  direrr = ERR;
  1205.                     
  1206.         /* strip off root and SLASH and copy to localdir */
  1207.         ptr = charnm1 + strlen(root) + 1;
  1208.         strcpy(lcldir, ptr);
  1209.  
  1210.     }
  1211.  
  1212.     return(NOERR);
  1213.  
  1214. }
  1215.  
  1216. zmess_(s, fd, length)
  1217. char *s;
  1218. int *fd;
  1219. long int length;
  1220. {
  1221.  
  1222.     /* output an f77 string terminated by a period to the file
  1223.        associated with the file descriptor fd. A trailing NEWLINE is
  1224.           appended to the line. A period is denoted by '..' */
  1225.  
  1226.     int newline = NEWLINE;
  1227.  
  1228.     zchout_(s, fd, length);
  1229.     putch_( &newline, fd);
  1230.  
  1231. }
  1232.  
  1233. zoblnk_(n, fd)
  1234. int *n, *fd;
  1235. {
  1236.  
  1237.     int i, blank = BLANK;
  1238.  
  1239.     /* output n blanks to the file fd */
  1240.  
  1241.     for (i = 1; i<=*n ; i++)
  1242.          putch_( &blank, fd);
  1243.  
  1244. }
  1245.  
  1246. zpos_(pos,fd)
  1247. int *pos, *fd;
  1248.  
  1249. {
  1250.     /* move the file pointer of the sequential file associated
  1251.        with the file pointer fd to a new character position.
  1252.            The next read (write) operation on this file will read
  1253.        (write) the next character after pos (relative to the
  1254.        current pointer).
  1255.        Note that a position request of 1 will skip a character.
  1256.        A negative value of pos has no effect.
  1257.        Positioning a device file has no effect. */
  1258.  
  1259.     /* UNIX DEPENDENT */
  1260.  
  1261.     /* repositioning the file pointer when the file is open for
  1262.        writing will effectively result in a sequence of nulls
  1263.        being written into the hole */
  1264.  
  1265.     long int offset;
  1266.     struct fdinfo *ptr;
  1267.     int nchars;
  1268.  
  1269.     /* check for valid file descriptor */
  1270.     if ( checkfd(*fd) != FILES ) return;
  1271.  
  1272.     if (*pos <= 0 ) return;
  1273.     ptr = &files[*fd];
  1274.  
  1275.     /* if open in write mode dump the current buffer
  1276.        - you get what you deserve as far as trailing
  1277.        blanks are concerned ! */
  1278.     if(ptr -> caccess == WRITE){
  1279.            write(*fd, ptr->buffer, ptr->chrleft);
  1280.         offset = *pos;
  1281.     }
  1282.  
  1283.     else {  /* current access to file is READ */
  1284.     
  1285.     /* calculate the real current position within the file by
  1286.        taking into account the buffer contents */
  1287.         nchars = ptr->count + ptr->chrleft;
  1288.         if (*pos < nchars) {
  1289.         
  1290.         /* repositioning is still within the buffer */
  1291.             if (*pos <= ptr->count) {
  1292.                 /* repositioning is still within a
  1293.                    block of blanks */
  1294.                 ptr->count -= *pos;
  1295.                 return;
  1296.             }
  1297.             else {
  1298.                 /* reposition within buffer */
  1299.                 nchars = *pos - ptr->count;
  1300.                 ptr->count = 0;
  1301.                 ptr->chrleft -= nchars;
  1302.                 ptr->bufp += nchars;
  1303.                 return;
  1304.             }
  1305.         }
  1306.  
  1307.         else
  1308.             /* need to reposition using lseek */
  1309.             offset = *pos - nchars;
  1310.      }
  1311.  
  1312.     /* zero counts etc ready for next read/write to file */
  1313.     ptr-> chrleft = 0;
  1314.     ptr->count = 0;
  1315.     ptr->bufp = ptr->buffer;
  1316.     lseek(*fd, offset, 1);
  1317.  
  1318. }
  1319.  
  1320. xputc_(ch)
  1321. int *ch;
  1322.  
  1323. {
  1324.     /* put a character out on the standard output file stdout */
  1325.  
  1326.     /* implemented as single character output for prompts */
  1327.     char c, junk;
  1328.     zcitoc_(&c,1L,ch,&junk);
  1329.     write(STDOUT, &c, 1);
  1330.  
  1331. }
  1332.  
  1333. zprmpt_(s)
  1334. int *s;
  1335. {
  1336.  
  1337.         char c,junk;
  1338.     /* output the IST string s to stderr - without adding a
  1339.        trailing NEWLINE */
  1340.     
  1341.     while(*s != EOS){
  1342.                zcitoc_(&c,1L,s,&junk);
  1343.                s++;
  1344.                write(STDERR,&c,1);
  1345.                }
  1346. }
  1347.  
  1348. zptint_(value, width, fd)
  1349. int *value, *width, *fd;
  1350.  
  1351. {
  1352.     /* write the number value out to the sequential file
  1353.        associated with the file descriptor fd in a field
  1354.        of width width. If the length of the number as a
  1355.        string is <= width it is blank filled and right
  1356.        justified, else the number is output in a wider field */
  1357.  
  1358.     int ist[MAXLINE], length;
  1359.  
  1360.     /* convert number to IST string */
  1361.     length = MAXLINE;
  1362.     length = itoc_(value, &ist[0], &length);
  1363.  
  1364.     /* output the requisite number of blanks */
  1365.     length = *width - length;
  1366.     zoblnk_(&length, fd);
  1367.     putlin_(&ist[0], fd);
  1368.  
  1369. }
  1370.  
  1371. zptmes_(buffer, fd)
  1372. int *buffer, *fd;
  1373. {
  1374.  
  1375.     int newline = NEWLINE;
  1376.     
  1377.     /* put a message out on the sequential file fd */
  1378.  
  1379.     putlin_(buffer, fd);
  1380.     putch_( &newline, fd);
  1381.  
  1382. }
  1383.  
  1384. zptstr_(string, width, fd)
  1385. int *string, *width, *fd;
  1386. {
  1387.  
  1388.     /* output the string string to the sequential file with
  1389.       associated file descriptor fd and justified in a field of width width
  1390.  
  1391.           width > 0  => string right justified
  1392.           width < 0  => string left justified
  1393.  
  1394.           length(string) > abs(width)  => normal output */
  1395.  
  1396.       int len, i, blank = BLANK;
  1397.  
  1398.       len = length_(string);
  1399.  
  1400.       /* width > 0 output leading spaces for right justification */
  1401.       if (width >= 0)
  1402.           for (i=len+1; i <= *width; i++) putch_(&blank, fd);
  1403.  
  1404.       /* right justify output string after leading blanks
  1405.          left justify output string ( width < 0 ) */
  1406.      while (*string != EOS) {
  1407.          putch_(string, fd);
  1408.          string++;
  1409.      }
  1410.  
  1411.      /* right justify now finished */
  1412.      if (width >= 0) return;
  1413.  
  1414.      /* left justify - output trailing blanks */
  1415.      for (i=len+1; i<= -*width; i++) putch_(&blank, fd);
  1416.      return;
  1417.  
  1418. }
  1419.  
  1420. zputch_(ch, fd)
  1421. int *fd;
  1422. char *ch;
  1423. {
  1424.  
  1425.     /* output an f77 character to the file associated with the file
  1426.        descriptor fd */
  1427.  
  1428.     int junk;
  1429.     
  1430.     junk = zcctoi_(ch, &junk);
  1431.     putch_(&junk, fd);
  1432.  
  1433. }
  1434.  
  1435. zrddir_(name)
  1436. int *name;
  1437. {
  1438.  
  1439.     /* returns the name of the next entry in the local directory.
  1440.        This is a sequential operation, to restart reading a
  1441.        directory it is necessary to call zlocal. On UNIX we
  1442.        ignore "." and ".." */
  1443.  
  1444. #ifdef HPUX
  1445.     struct dirent *dp, *trddir();
  1446. #else
  1447.     struct direct *dp, *trddir();
  1448. #endif
  1449.  
  1450.     /* check the global error flag */
  1451.     if (direrr == ERR) return(ERR);
  1452.  
  1453.     /* get the next entry and check it isn't "." or ".." */
  1454.  
  1455.     /* use a system call */
  1456.     while (((dp = readdir(dirp)) != NULLST) && (strcmp(dp->d_name, ".") ==0
  1457.             || strcmp(dp->d_name, "..") == 0));
  1458.     /* if NULLST have we an EOF condition */
  1459.     if (dp == NULLST) {
  1460.         direrr = EOF;
  1461.  
  1462.         return(EOF);
  1463.     }
  1464.  
  1465.     /* otherwise return the name */
  1466.     chist_(dp->d_name, name, strlen(dp->d_name));
  1467.     direrr = NOERR;
  1468.     return(NOERR);
  1469. }
  1470.  
  1471. zrenam_(path1, path2)
  1472. int *path1, *path2;
  1473. {
  1474.  
  1475.     /* Rename a file. the file referred to by path1 is renamed path2.
  1476.        path1 and path2 must be of the same type ('host' or 'plain')
  1477.        and path1 must exist while path2 must not exist */
  1478.  
  1479.        int pid, status, w;
  1480.        struct filinfo finf1, finf2;
  1481.        char file1[MAXPATH], file2[MAXPATH];
  1482.  
  1483.        /* generate full path anmes */
  1484.        mkfilnm(path1, file1, &finf1);
  1485.        mkfilnm(path2, file2, &finf2);
  1486.  
  1487.        /* check for valid move both host files or both plain files */
  1488.        if ((finf1.ftype1 == HOST && finf2.ftype1 == HOST) ||
  1489.            (finf1.ftype1 == VFS && finf2.ftype1 == VFS &&
  1490.             finf1.subtype == PLAIN && finf2.subtype == PLAIN)) {
  1491.  
  1492.                 /* check file1 exists and file2 does not */
  1493.                 if (finf1.exists == NO || finf2.exists == YES) return(ERR);
  1494.                 if ((pid = fork()) == -1) return(ERR);
  1495.  
  1496.                 if (pid == 0) execl(MVPATH, "mv", file1, file2, (char *)0);
  1497.                 while ((w = wait(&status)) != pid && w != -1);
  1498.  
  1499.                 if( w == -1) return(ERR);
  1500.  
  1501.                 return(NOERR);
  1502.             }
  1503.  
  1504.             /* invalid arguments */
  1505.             return(ERR);
  1506.  
  1507. }
  1508.  
  1509. zspool_()
  1510. {
  1511.  
  1512.     /* close the current standard list file and open a new one.
  1513.        Flush buffer associated with fd = STDLST.
  1514.        Print file using lpr with flags LPRFLAGS.
  1515.        Start a new spool file */
  1516.  
  1517.     struct stat buf;
  1518.     int access = READWRITE, istname[MAXPATH];
  1519.     int fd = STDLST;
  1520.     int pid, status, w;
  1521.  
  1522.     close(fd);
  1523.  
  1524.     /* don't list it if it doesn't exist (impossible !?) or is empty */
  1525.     if (stat(files[fd].filenam, &buf) != -1 && buf.st_size > 0) {
  1526.  
  1527.             if ((pid = fork()) == -1) return(ERR);
  1528.  
  1529.             if (pid == 0) {
  1530.             execl(LPRPATH, LPR, files[fd].filenam, (char *)0);
  1531.               exit(1);
  1532.          }
  1533.             while ((w = wait(&status)) != pid && w != -1);
  1534.  
  1535.             if( w == -1) return(ERR);
  1536.         }
  1537.  
  1538.         /* create a fresh spool file */
  1539.     status = crtzlng(files[fd].filenam, access, fd);
  1540.     if (status != fd) remark_("spooler file recreation error.",30L);
  1541.     if (status != fd) printf("status,fd = %d , %d \n",status,fd);
  1542.  
  1543.         return(NOERR);
  1544.  
  1545. }
  1546.  
  1547. zstamp_(path, date, time)
  1548. int *path, *date, *time;
  1549. {
  1550.  
  1551.     /* Return the last modified date and time stamps of the specified
  1552.        file or directory in the PFS. It is an error to try to get the
  1553.        time stamp for a host or non-existant file. The time stamp
  1554.        may be converted to an IST string using the routine ZTIMES. The
  1555.        date and time values are calculated as follows
  1556.  
  1557.        DATE = ((year - 1983)*13 + month)*32 + day
  1558.        TIME = (hour*61 + minute) *61 + second
  1559.      */
  1560.  
  1561.      struct tm tmstr, *localtime();
  1562.      struct stat buf;
  1563.      struct filinfo finf;
  1564.      char charnm1[MAXPATH];
  1565.  
  1566.      /* get the file information */
  1567.      mkfilnm(path, charnm1, &finf);
  1568.      if (finf.ftype1 != VFS || finf.exists != YES) return(ERR);
  1569.  
  1570.      /* get the last modified time */
  1571.      stat(charnm1, &buf);
  1572.      zstclk = buf.st_mtime;
  1573.      tmstr = *localtime(&zstclk);
  1574.  
  1575.      *date = ((tmstr.tm_year - 83)*13 + tmstr.tm_mon)*32 +
  1576.          tmstr.tm_mday;
  1577.  
  1578.      *time = (tmstr.tm_hour*61 + tmstr.tm_min)*61  + tmstr.tm_sec;
  1579.  
  1580.      return(NOERR);
  1581.  
  1582. }
  1583.  
  1584. zstate_(name)
  1585. int *name;
  1586. {
  1587.  
  1588.     /* find the status of the file name. This routine may be used to
  1589.       find the status of a direct access or sequential files
  1590.       N.B. you can't tell the difference on UNIX
  1591.  
  1592.       Preconnected units always exist */
  1593.  
  1594.     struct filinfo finf;
  1595.     char charnm1[MAXPATH];
  1596.  
  1597.     mkfilnm(name, charnm1, &finf);
  1598.  
  1599.     /* invalid file type */
  1600.     if (finf.ftype1 == ERR) return(ERR);
  1601.  
  1602.     /* Preconnected unit */
  1603.     if (finf.ftype1 == DEVICE) return(YES);
  1604.  
  1605.     /* exists or not */
  1606.     return(finf.exists);
  1607.  
  1608. }
  1609.  
  1610. ztidy_()
  1611. {
  1612.     
  1613.     /* close all sequential and direct access files currently
  1614.        open to this program */
  1615.  
  1616.     int fd;
  1617.  
  1618.     for (fd = FIRSTFD; fd < MAXFILE ; fd++) close_(&fd);
  1619.  
  1620. }
  1621.  
  1622. ztouch_(path)
  1623. int *path;
  1624. {
  1625.  
  1626.     /* update the time stamp for a specified plain or directory
  1627.        file. It is an error to try to update the time stamp
  1628.        of a host or non-existant file */
  1629.  
  1630.     struct filinfo finf;
  1631.     char filenam[MAXPATH];
  1632.     int pid, status, w;
  1633.  
  1634.     mkfilnm(path, filenam, &finf);
  1635.  
  1636.     /* check exists and is in the vfs */
  1637.     if (finf.ftype1 != VFS || finf.exists != YES) return(ERR);
  1638.  
  1639. {
  1640.     struct timeval tvp[2];
  1641.     struct timezone tz;
  1642.     
  1643.     gettimeofday(tvp, &tz);
  1644.     tvp[1] = tvp[0];
  1645. #ifdef HPUX                    /*+++*/
  1646.     utime(filenam,tvp);    /*+++*/
  1647. #else                          /*+++*/
  1648.     utimes(filenam, tvp);
  1649. #endif                         /*+++*/
  1650. }
  1651.  
  1652.     
  1653.     return(NOERR);
  1654.  
  1655. }
  1656.